package com.tcoiss.datafactory.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.tcoiss.common.core.constant.Constants;
import com.tcoiss.common.core.domain.R;
import com.tcoiss.common.core.enums.ErroEnums;
import com.tcoiss.common.core.exception.CustomException;
import com.tcoiss.common.core.utils.DateUtils;
import com.tcoiss.common.core.utils.SecurityUtils;
import com.tcoiss.common.core.utils.StringUtils;
import com.tcoiss.common.redis.service.RedisService;
import com.tcoiss.common.component.api.RemoteApiService;
import com.tcoiss.common.component.api.model.ApiParam;
import com.tcoiss.datafactory.domain.BusTable;
import com.tcoiss.datafactory.domain.BusTableColumn;
import com.tcoiss.datafactory.domain.vo.TablePageVO;
import com.tcoiss.datafactory.domain.vo.TableVO;
import com.tcoiss.datafactory.mapper.BusTableMapper;
import com.tcoiss.datafactory.service.IBusTableColumnService;
import com.tcoiss.datafactory.service.IBusTableService;
import com.tcoiss.datafactory.service.IDynamicSqlService;
import com.tcoiss.datafactory.thread.SyncThreadHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.dao.DataAccessException;
import org.springframework.stereotype.Service;

import java.net.URLEncoder;
import java.sql.JDBCType;
import java.util.*;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * 业务表Service业务层处理
 *
 * @author zw
 * @date 2021-04-20
 */
@Service
public class BusTableServiceImpl extends ServiceImpl<BusTableMapper, BusTable> implements IBusTableService {

    @Autowired
    private RemoteApiService remoteApiService;

    @Autowired
    private RedisService redisService;

    @Autowired
    private IDynamicSqlService iDynamicSqlService;

    @Autowired
    private SyncThreadHandler syncThreadHandler;

    @Autowired
    private IBusTableColumnService iBusTableColumnService;

    private static final Logger log = LoggerFactory.getLogger(BusTableServiceImpl.class);

    //核心线程数
    @Value("${book.core.poolsize}")
    private int threadSum;

    private final static long EXPIRE_TIME = Constants.KD_TOKEN_EXPIRE * 30;

    @Override
    public List<BusTable> queryList(BusTable busTable) {
        LambdaQueryWrapper<BusTable> lqw = Wrappers.lambdaQuery();
        if (StringUtils.isNotBlank(busTable.getBusTableName())) {
            lqw.like(BusTable::getBusTableName, busTable.getBusTableName());
        }
        if (StringUtils.isNotBlank(busTable.getBusTableComment())) {
            lqw.like(BusTable::getBusTableComment, busTable.getBusTableComment());
        }
        if (StringUtils.isNotBlank(busTable.getSyncApiCode())) {
            lqw.eq(BusTable::getSyncApiCode, busTable.getSyncApiCode());
        }
        if (StringUtils.isNotBlank(busTable.getBusGroupName())) {
            lqw.like(BusTable::getBusGroupName, busTable.getBusGroupName());
        }
        if (StringUtils.isNotBlank(busTable.getTableType())) {
            lqw.eq(BusTable::getTableType, busTable.getTableType());
        }
        if (busTable.getTableStatus() != null) {
            lqw.eq(BusTable::getTableStatus, busTable.getTableStatus());
        }
        return this.list(lqw);
    }

    @Override
    public List<TableVO> findList(BusTable busTable) {
        List<TableVO> vos = new LinkedList<>();
        List<BusTable> list = this.queryList(busTable);
        for (int i = 0; i < list.size(); i++) {
            BusTable table = list.get(i);
            List<BusTableColumn> columns = iBusTableColumnService.getColumnsByName(table.getBusTableName());
            for (int j = 0; j < columns.size(); j++) {
                TableVO vo = new TableVO();
                BusTableColumn column = columns.get(j);
                vo.setTableName(table.getBusTableName());
                vo.setTableComment(table.getBusTableComment());
                vo.setBusGroupName(table.getBusGroupName());
                vo.setSyncApiCode(table.getSyncApiCode());
                vo.setTableType(table.getTableType());
                vo.setColumnName(column.getColumnName());
                vo.setKdColumnName(column.getKdColumnName());
                vo.setDataModel(column.getDataModel());
                vo.setColumnComment(column.getColumnComment());
                vos.add(vo);
            }
        }
        return vos;
    }


    /**
     * 保存业务表后会形成业务对象后面可以根据业务对象编码来查找api
     *
     * @param busTable
     * @return
     */
    @Override
    public boolean saveTable(BusTable busTable) {
        if (checkBusTable(busTable.getBusTableName())) {
            return this.save(busTable);
        }
        return false;
    }

    @Override
    public boolean updateBusTableById(BusTable busTable) {
        if (checkBusTable(busTable)) {
            return this.updateById(busTable);
        }
        return false;
    }

    @Override
    public BusTable getBusTableByName(String tableName) {
        LambdaQueryWrapper<BusTable> lqw = Wrappers.lambdaQuery();
        if (StringUtils.isNotBlank(tableName)) {
            lqw.eq(BusTable::getBusTableName, tableName);
        }
        BusTable busTable = this.getOne(lqw);
        List<BusTableColumn> columns = iBusTableColumnService.getColumnsByName(tableName);

        return busTable.setColumns(columns);
    }

    @Override
    public Map<String, Object> getBusTableById(Long tableId) {
        Map<String, Object> map = new HashMap<>();
        //查询表详细配置以及表字段列表信息
        BusTable busTable = this.getById(tableId);
        List<BusTableColumn> columns = new ArrayList<>();
        if (busTable != null) {
            columns = iBusTableColumnService.getColumnsByName(busTable.getBusTableName());
        }
        map.put("rows", columns);
        map.put("info", busTable);
        return map;
    }

    /**
     * 提交业务表
     *
     * @param busTable
     * @return
     */
    @Override
    public boolean updateBusTable(BusTable busTable) {
        this.checkBusTable(busTable);
        BusTable table = this.getById(busTable.getTableId());
        List rows = redisService.getCacheObject(table.getBusTableName());
        if (!redisService.deleteObject(table.getBusTableName())) {
            //throw new DataException("405",null,"删除缓存失败");
        }
        redisService.setCacheObject(busTable.getBusTableName(), rows,EXPIRE_TIME, TimeUnit.SECONDS);
        List<BusTableColumn> columns = busTable.getColumns();
        columns.stream().map(column -> {
            if (!column.getTableName().equals(busTable.getBusTableName())) {
                column.setTableName(busTable.getBusTableName());
            }
            return column;
        });
        if (this.updateById(busTable)) {
            return iBusTableColumnService.saveOrUpdateBatch(columns);
        }
        return false;
    }

    /**
     * @param tableName
     * @return
     */
    private boolean createTable(String tableName,String dbName, String tableType, List<BusTableColumn> columns) {
        //先判断是否存在表
        if (iDynamicSqlService.exitTable(tableName,dbName)) {
            iDynamicSqlService.dropTable(tableName,dbName, tableType);
        }
        //根据业务表结构生成建表sql并执行
        return iDynamicSqlService.createTable(tableName,dbName, columns);
    }

    /**
     * @param table
     * @return
     */
    private int insetTable(BusTable table, List<BusTableColumn> columns) {
        columns.removeIf(column -> column.getIsAuto().equals("1"));
        List<String> columnNames = columns.stream().map(column -> column.getColumnName()).collect(Collectors.toList());
        try {
            //从redis中取出数据集合
            List<List<Object>> datas = redisService.getCacheObject(table.getBusTableName());
            if(datas==null){
                throw new CustomException("初始化表数据时报错如下： 无可初始化的结构数据");
            }
            List<Object[]> list = new ArrayList<>();
            for (List<Object> row : datas) {
                list.add(row.toArray());
            }
            return iDynamicSqlService.batchInsert(table, columnNames.toArray(new String[columnNames.size()]), list);
        } catch (DataAccessException e) {
            e.printStackTrace();
            throw new CustomException("初始化表数据时报错如下：" ,e);
        }
    }

    //同步表结构
    private List<BusTableColumn> getColumnsByApi(ApiParam apiParam, List<BusTableColumn> columns) {
        //根据api调用获取表结构JSON串
        columns.removeIf(column -> column.getIsAuto().equals("1"));
        List<List<Object>> rows = new ArrayList<>();
        R<Map<String, Object>> r = remoteApiService.executeKdApi(apiParam);
        if (r.getCode() == 200) {
            Map<String, Object> map = r.getData();
            if (map.get("success").toString().equals("true")) {
                Map<String, Object> data = (Map<String, Object>) map.get("data");
                int count = Integer.valueOf(data.get("count").toString());
                if (count == 0) {
                    //throw new ApiException("405",null,"未查询到可同步数据");
                    redisService.setCacheObject(columns.get(0).getTableName(), rows,EXPIRE_TIME,TimeUnit.SECONDS);
                }
                List<Object> header = (List) data.get("header");
                for (int i = 0; i < columns.size(); i++) {
                    BusTableColumn column = columns.get(i);
                    Map<String, Object> headerMap = (Map) header.get(i);
                    column.setDataType(headerMap.get("type").toString());
                }
                if (columns.size() > 0) {
                    rows = (List) data.get("rows");
                    rows.removeIf(row -> (row.get(0).toString()).equals("0") );
                    for(List<Object> row: rows){
                        Collections.replaceAll(row, "null", "");
                        Collections.replaceAll(row, "0E-10", "0");
                    }
                    //将数据保存到redis，key值为表名
                    redisService.setCacheObject(columns.get(0).getTableName(), rows,EXPIRE_TIME, TimeUnit.SECONDS);
                    return columns;
                }
            } else {
                throw new CustomException(ErroEnums.APIERRO.getCode(), new Object[]{apiParam}, ErroEnums.APIERRO.getInfo()+r.getData().toString());
            }
        } else {
             throw new CustomException(ErroEnums.APIERRO.getCode(), new Object[]{apiParam} , ErroEnums.APIERRO.getInfo()+r.getMsg());
        }
        return null;
    }

    private boolean updateColumnsByApi(ApiParam apiParam, String tableName) {
        //根据api调用获取表结构JSON串
        List<List<Object>> rows = new ArrayList<>();
        R<Map<String, Object>> r = remoteApiService.executeKdApi(apiParam);
        if (r.getCode() == 200) {
            Map<String, Object> map = r.getData();
            if (map.get("success")!=null&&map.get("success").toString().equals("true")) {
                Map<String, Object> data = (Map<String, Object>) map.get("data");
                int count = Integer.valueOf(data.get("count").toString());
                if (count == 0) {
                    //throw new ApiException("405",null,"未查询到可同步数据");
                    redisService.setCacheObject(tableName, rows,EXPIRE_TIME,TimeUnit.SECONDS);
                }
                if (count > 0) {
                    rows = (List) data.get("rows");
                    rows.removeIf(row -> String.valueOf(row.get(0)).equals("0") || String.valueOf(row.get(0)).equals(""));
                    //仅同步10条记录
                    List<List<Object>> newrows = new ArrayList();
                    if (rows.size() > 10) {//判断list长度
                        newrows = rows.subList(0, 9);//取前9条数据
                    } else {
                        newrows = rows;
                    }
                    for(List<Object> row: newrows){
                        Collections.replaceAll(row, "null", "");
                        Collections.replaceAll(row, "0E-10", "0");
                    }
                    //将数据保存到redis，key值为表名
                    redisService.setCacheObject(tableName, newrows,EXPIRE_TIME,TimeUnit.SECONDS);
                }
                return true;
            } else {
                throw new CustomException(ErroEnums.APIERRO.getCode(), new Object[]{apiParam}, ErroEnums.APIERRO.getInfo()+r.getData().get("message"));
            }
        } else {
            throw new CustomException(ErroEnums.APIERRO.getCode(), new Object[]{apiParam}, ErroEnums.APIERRO.getInfo()+r.getMsg());
        }
    }


    /**
     * 初始化表数据
     *
     * @param id
     * @return
     */
    @Override
    public boolean initTable(Long id) {
        try{
            BusTable busTable = this.getById(id);
            if (busTable.getTableStatus() == 1) {
                throw new CustomException(ErroEnums.DATAERRO.getCode(), new String[]{busTable.getBusTableName()
                }, "表已初始化，请勿重复操作");
            }
            /**
             * 1 创建表,或视图
             */
            boolean flag = false;
            List<BusTableColumn> columns = this.iBusTableColumnService.getColumnsByName(busTable.getBusTableName());
            List<String> columnNames = columns.stream().map(column -> column.getColumnName()).collect(Collectors.toList());
            if (busTable.getTableType().equals("view")) {//创建视图
                flag = iDynamicSqlService.createView(busTable.getBusTableName(),busTable.getDbName(), columnNames, busTable.getSqlScript());
            } else {
                flag = this.createTable(busTable.getBusTableName(),busTable.getDbName(), busTable.getTableType(), columns);
                if (flag) {
                    if (busTable.getTableType().equals("bill")||busTable.getTableType().equals("base")||
                            busTable.getTableType().equals("report")) {
                        //根据表名和分录号对数据进行分组，同步所有的表数据
                        int num = this.insetTable(busTable,columns);
                        if (num < 0) {
                            throw new CustomException(ErroEnums.DATAERRO.getCode(), null, "初始化表时插入表数据失败");
                        }
                        redisService.deleteObject(busTable.getBusTableName());
                    }

                }
            }
            if(flag){
                //更新表状态为已初始化
                busTable.setTableStatus(1);
                busTable.setUpdateTime(new Date());
                return this.updateById(busTable);
            }
        }catch (Exception e){
            e.printStackTrace();
            throw new CustomException("初始化表失败"+e.getMessage(), e);
        }
        return false;
    }
    /**
     * 反初始化表数据
     *
     * @param id
     * @return
     */
    @Override
    public boolean backInitTable(Long id){
        BusTable busTable = this.getById(id);
        busTable.setTableStatus(0);
        busTable.setUpdateTime(null);
        return this.updateById(busTable);
    }

    //全量同步
    @Override
    public int syncAllDataByApi(BusTable busTable, String script) {
        if (iDynamicSqlService.delete(busTable.getBusTableName(),busTable.getDbName())) {
            return syncDataByApi(busTable, new JSONObject(),"",true);
        } else {
            throw new CustomException(ErroEnums.DATAERRO.getCode(), null, "全量同步清空数据时发生异常");
        }
    }

    @Override
    public List<Map<String, Object>> queryTableDate(TablePageVO pageVO) {
        String whereSql = "";
        if(pageVO.getId()!=null){
            Long id = pageVO.getId();
            whereSql = "where id = "+id ;
        }
        int pageNum = pageVO.getPageNum();
        int pageSize = pageVO.getPageSize();
        whereSql = whereSql+" LIMIT "+pageNum+","+ pageSize;
        //查询表详细配置以及表字段列表信息
        BusTable busTable = this.getById(pageVO.getTableId());
        List<BusTableColumn> columns = getColumns(pageVO.getTableId());
        List<String> columnNames = columns.stream().map(column -> column.getColumnName()).collect(Collectors.toList());
        return iDynamicSqlService.query(busTable.getBusTableName(),busTable.getDbName(), whereSql, columnNames.toArray(new String[columnNames.size()]));
    }
    @Override
    public Integer queryTableCount(TablePageVO pageVO) {
        BusTable busTable = this.getById(pageVO.getTableId());
        return iDynamicSqlService.getCount(pageVO.getTableName(),busTable.getDbName());
    }

    @Override
    public boolean removeByColumnId(Long columnId) {
        return iBusTableColumnService.removeById(columnId);
    }

    @Override
    public List<BusTableColumn> getColumns(Long tableId) {
        //查询表详细配置以及表字段列表信息
        BusTable busTable = this.getById(tableId);
        List<BusTableColumn> columns = new ArrayList<>();
        if (busTable != null) {
            return iBusTableColumnService.getColumnsByName(busTable.getBusTableName());
        }else{
            return null;
        }
    }

    @Override
    public int syncLinkDataByApi(BusTable table, String script, String msgObjectId) {
        JSONObject jsonObject = JSONObject.parseObject(script);
        //将关联脚本作为查询条件过滤金碟数据
        try {
            String filterScript = jsonObject.get("filter").toString();
            if (StringUtils.isNotBlank(msgObjectId) && filterScript.contains("?")) {
                filterScript = filterScript.replace("?", msgObjectId);
            }
            jsonObject.put("filter", filterScript);
        } catch (DataAccessException e) {
            throw new CustomException("同步表" + table.getBusTableName() + "增量数据时查询表数据异常: ",  e);
        }
        return syncDataByApi(table, jsonObject,msgObjectId,false);
    }


    //增量同步
    @Override
    public int syncAddDataByApi(BusTable busTable, String script, Date updateTime) {
        JSONObject jsonObject = JSONObject.parseObject(script);
        //先查询当前业务表最新的更新时间，作为过滤条件查询苍穹数据
        try {
            //Date updateTime = iDynamicSqlService.queryNewestTime(busTable.getBusTableName(), "modify_time");
            Object filter = jsonObject.get("filter");
            Object startday = jsonObject.get("startday");
            Object endday = jsonObject.get("endday");
            if(filter!=null){
                String filterScript = String.valueOf(filter);
                filterScript = URLEncoder.encode(filterScript, "UTF-8");
                filterScript = filterScript.replace("now",DateUtils.dateTimeNow(DateUtils.YYYY_MM_DD));
                filterScript = filterScript.replace("last",DateUtils.getBeginDayOfYesterday(DateUtils.YYYY_MM_DD));
                filterScript = filterScript.replace("updateTime",DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD, updateTime));
                jsonObject.put("filter", filterScript);

            }
            if(startday!=null){
                JSONObject startday1 = (JSONObject)startday;
                startday1.put("value","2022-01-01");
                //startday1.put("value",DateUtils.getBeginDayOfYesterday(DateUtils.YYYY_MM_DD));
                String startdayScript = JSONObject.toJSONString(startday);
                jsonObject.put("startday", startdayScript);
            }
            if(endday!=null){
                JSONObject endday1 = (JSONObject)startday;
                endday1.put("value","2022-01-19");
                //endday1.put("value",DateUtils.getBeginDayOfYesterday(DateUtils.YYYY_MM_DD));
                String enddayScript = JSONObject.toJSONString(endday1);
                jsonObject.put("endday", enddayScript);
            }


        } catch (Exception e) {
            throw new CustomException("同步表" + busTable.getBusTableName() + "增量数据时查询表数据异常: ",  e);
        }
        return syncDataByApi(busTable, jsonObject,"",false);
    }

    private int syncDataByApi(BusTable busTable, JSONObject jsonObject, String msgObjectId,boolean isall) {
        busTable.getColumns().removeIf(column -> column.getIsAuto().equals("1"));
        List<String> kdColumnNames = busTable.getColumns().stream().map(column -> column.getKdColumnName()).collect(Collectors.toList());
        String select = StringUtils.join(kdColumnNames.toArray(), ",");
        //jsonObject.put("filter", filter);
        jsonObject.put("select", select.replaceAll(" ", ""));
        ApiParam apiParam = new ApiParam();
        apiParam.setApiCode(busTable.getSyncApiCode());
        apiParam.setParam(jsonObject);
        List<String> columnNames = busTable.getColumns().stream().map(column -> column.getColumnName()).collect(Collectors.toList());
        R<Map<String, Object>> r = remoteApiService.executeKdApi(apiParam);
        if (r.getCode() == 200) {
            Map<String, Object> map = r.getData();
            if (String.valueOf(map.get("success")).equals("true")) {
                Map<String, Object> data = (Map<String, Object>) map.get("data");
                int count = Integer.valueOf(data.get("count").toString());
                List<List<String>> rows = (List) data.get("rows");
                if(count == 0 && StringUtils.isNotEmpty(msgObjectId)){
                    if(iDynamicSqlService.deleteByField(busTable.getBusTableName(),busTable.getDbName(),"number",msgObjectId)){
                        return 1;
                    }
                }
                if(count == 0){
                    return 1;
                }
                StringBuilder erros = new StringBuilder();
                int num = 0;
                List<Object[]> list = new ArrayList<>();
                for (List<String> row : rows) {
                    Collections.replaceAll(row, "null", "");
                    Collections.replaceAll(row, "0E-10", "0");
                    list.add(row.toArray());
                }
                log.info("当前总数据条数："+count);
                //批量保存数据 当数据量超20000时采用多线程插入数据
                if(count>20000) {
                    //接收集合各段的 执行的返回结果
                    List<Future<String>> futureList = new ArrayList<Future<String>>();
                    //集合总条数
                    if (list != null) {
                        int listSize = list.size();
                        int runSize = (listSize / 20000) + 1;  //开启的线程数
                        int listStart, listEnd;
                        int subSize = threadSum;
                        //当总条数不足threadSum条时 用总条数 当做线程切分值
                        if (threadSum > runSize) {
                            subSize = runSize;
                        }
                        //将list 切分多份 多线程执行
                        for (int i = 0; i < subSize; i++) {
                            //计算切割  开始和结束
                            listStart = listSize / subSize * i;
                            listEnd = listSize / subSize * (i + 1);
                            //最后一段线程会 出现与其他线程不等的情况
                            if (i == subSize - 1) {
                                listEnd = listSize;
                            }
                            //数据切断
                            List<Object[]> sunList = list.subList(listStart, listEnd);
                            //每段数据集合并行入库
                            futureList.add(syncThreadHandler.syncUpdateData(busTable, columnNames.toArray(new String[columnNames.size()]), sunList,isall, i));
                        }
                        //对各个线程段结果进行解析
                        for (Future<String> future : futureList) {
                            String str;
                            if (null != future) {
                                try {
                                    str = future.get().toString();
                                    erros.append(str);

                                    log.info("current thread id =" + Thread.currentThread().getName() + ",result=" + str);
                                } catch (InterruptedException | ExecutionException e) {
                                    log.info("线程运行异常！");
                                    throw new CustomException(e.getMessage());
                                }
                            } else {
                                log.info("线程运行异常！");
                                throw new CustomException(ErroEnums.DATAERRO.getCode(),null,ErroEnums.DATAERRO.getInfo()+"线程运行异常");
                            }

                        }
                        num = list.size();
                    }
                }else{
                    try {
                        if(isall){
                            num = iDynamicSqlService.batchInsert(busTable, columnNames.toArray(new String[columnNames.size()]), list);
                        }else{
                            num = iDynamicSqlService.batchUpdateOrInsert(busTable,columnNames.toArray(new String[columnNames.size()]), list);
                        }
                    } catch (DataAccessException e) {
                        throw new CustomException(ErroEnums.DATAERRO.getCode(), ErroEnums.DATAERRO.getInfo() + "同步表" + busTable.getBusTableName() + "数据时插入表数据异常: " ,e);
                    }
                }
                if(StringUtils.isNotEmpty(erros.toString())){
                    throw new CustomException(ErroEnums.DATAERRO.getCode(), new Object[]{busTable.getBusTableName()}, ErroEnums.DATAERRO.getInfo() + "同步表" + busTable.getBusTableName() + "数据时插入表数据异常: " + erros.toString());
                }
                long insertCount = 0L;
                try {
                    if(isall){
                        insertCount = iDynamicSqlService.getCount(busTable.getBusTableName(),busTable.getDbName());
                    }else {
                        insertCount = iDynamicSqlService.getCountByDateTime(busTable,busTable.getDbName());
                    }
                } catch (DataAccessException e) {
                    throw new CustomException(ErroEnums.DATAERRO.getCode(), ErroEnums.DATAERRO.getInfo() + "同步表" + busTable.getBusTableName() + "数据时插入表数据异常: " ,e);
                }
                if(insertCount != num){
                    throw new CustomException(ErroEnums.DATAERRO.getCode(),
                            new Object[]{busTable.getBusTableName()},
                            ErroEnums.DATAERRO.getInfo() + "应插入条数为:" + num + ",实际插入条数为:" + insertCount +
                            "差异数为:" + (num-insertCount));
                }
                log.info("执行数据完成：数据条数"+num);


                return num;

            } else {
                throw new CustomException(ErroEnums.APIERRO.getCode(), new Object[]{busTable.getBusTableName()}, ErroEnums.APIERRO.getInfo() + "同步表" + busTable.getBusTableName() + "数据时调用API:" + busTable.getSyncApiCode() + "接口时异常：" + map.get("message").toString());
            }
        } else {
            throw new CustomException(ErroEnums.APIERRO.getCode(), new Object[]{busTable.getBusTableName()}, ErroEnums.APIERRO.getInfo() + "同步表" + busTable.getBusTableName() + "数据时调用API:" + busTable.getSyncApiCode() + "接口时异常：" + r.getMsg());
        }
    }


    @Override
    public boolean syncTableJg(BusTable table) {
        List<BusTableColumn> columns = iBusTableColumnService.getColumnsByName(table.getBusTableName());
        columns.removeIf(column -> column.getIsAuto().equals("1"));
        List<String> columnNames = columns.stream().map(column -> column.getKdColumnName()).collect(Collectors.toList());
        ApiParam apiParam = new ApiParam();
        apiParam.setApiCode(table.getSyncApiCode());
        String select = StringUtils.join(columnNames.toArray(), ",");
        Map<String, Object> param = new HashMap<>();
        param.put("select", select.replaceAll(" ", ""));
//        if(table.getTableType().equals("bill")){//默认查询前天数据
//            param.put("filter","");
//        }
        apiParam.setParam(param);
        return updateColumnsByApi(apiParam, table.getBusTableName());
    }


    private boolean checkBusTable(BusTable table) {
        LambdaQueryWrapper<BusTable> lqw = Wrappers.lambdaQuery();
        if (StringUtils.isNotBlank(table.getBusTableName())) {
            lqw.eq(BusTable::getBusTableName, table.getBusTableName());
        }
        lqw.notIn(BusTable::getTableId, table.getTableId());
        if (this.list(lqw).size() > 0) {
            throw new CustomException(ErroEnums.DATAERRO.getCode(), new String[]{table.getBusTableName()}, ErroEnums.DATAERRO.getInfo() + "保存失败，表名已存在");
        }
        return true;

    }

    private boolean checkBusTable(String tableName) {
        LambdaQueryWrapper<BusTable> lqw = Wrappers.lambdaQuery();
        if (StringUtils.isNotBlank(tableName)) {
            lqw.eq(BusTable::getBusTableName, tableName);
        }
        if (this.list(lqw).size() > 0) {
            throw new CustomException(ErroEnums.DATAERRO.getCode(), new String[]{tableName}, ErroEnums.DATAERRO.getInfo() + "保存失败，表名已存在");
        }
        return true;

    }


    /**
     * 导入用户数据
     *
     * @param vos         用户数据列表
     * @param isUpdateSupport 是否更新支持，如果已存在，则进行更新数据
     * @return 结果
     */
    @Override
    public String importTable(List<TableVO> vos, boolean isUpdateSupport) {
        if (isUpdateSupport) {
            this.checkBusTable(vos.get(0).getTableName());
        }
        if (StringUtils.isNull(vos) || vos.size() == 0) {
            throw new CustomException(ErroEnums.BUSERRO.getCode(), null, ErroEnums.BUSERRO.getInfo() + "导入表数据不能为空！");
        }
        for (int i = 0; i < vos.size(); i++) {
            if (StringUtils.isEmpty(vos.get(i).getTableName())) {
                vos.remove(i--);
            }
        }
        //将获取到的导入数据保存到数据库中,对数据根据表名进行分组
        Map<String, List<TableVO>> tableMap = vos.stream()
                .collect(Collectors.groupingBy(TableVO::getTableName));
        if (tableMap.size() > 1) {
            throw new CustomException(ErroEnums.BUSERRO.getCode(), null, ErroEnums.BUSERRO.getInfo() + "仅支持单表导入！");
        }
        StringBuilder successMsg = new StringBuilder();
        BusTable busTable = new BusTable();
        busTable.setBusTableName(vos.get(0).getTableName());
        busTable.setBusGroupName(vos.get(0).getBusGroupName());
        busTable.setSyncApiCode(vos.get(0).getSyncApiCode());
        busTable.setBusTableComment(vos.get(0).getTableComment());
        busTable.setCreateBy(SecurityUtils.getUsername());
        busTable.setTableType(vos.get(0).getTableType());
        busTable.setCreateTime(new Date());

        List<BusTableColumn> columns = new ArrayList<>();
        for (int i = 0; i < vos.size(); i++) {
            TableVO vo = vos.get(i);
            BusTableColumn column = new BusTableColumn();
            column.setDataType("String");
            column.setColumnName(vo.getColumnName().trim());
            column.setTableName(vo.getTableName().trim());
            column.setKdColumnName(vo.getKdColumnName());
            column.setColumnType("varchar(100)");
            column.setColumnComment(vo.getColumnComment());
            column.setDataModel(vo.getDataModel());
            columns.add(column);
        }
        String[] types = new String[]{"bill", "base","report"};
        if (Arrays.asList(types).contains(busTable.getTableType())) {
            //调用api获取数据
            List<String> columnNames = vos.stream().map(column -> column.getKdColumnName()).collect(Collectors.toList());
            ApiParam apiParam = new ApiParam();
            apiParam.setApiCode(busTable.getSyncApiCode());
            String select = StringUtils.join(columnNames.toArray(), ",");
            Map<String, Object> param = new HashMap<>();
            param.put("select", select.replaceAll(" ", ""));
            apiParam.setParam(param);
            getColumnsByApi(apiParam, columns);
        }
        if (this.save(busTable)) {
            if (iBusTableColumnService.saveBatch(columns)) {
                successMsg.insert(0, "恭喜您，数据已全部导入成功！共 " + columns.size() + " 条，数据如下：");
            } else {
                throw new CustomException(ErroEnums.DATAERRO.getCode(), new String[]{"列数据为:" + columns}, ErroEnums.DATAERRO.getInfo() + "保存表的列数据异常");
            }
        } else {
            throw new CustomException(ErroEnums.DATAERRO.getCode(), new String[]{"保存表为:" + busTable.getBusTableName()}, ErroEnums.DATAERRO.getInfo() + "保存表数据异常");
        }
        return successMsg.toString();
    }

    @Override
    public boolean removeTablesByIds(List<Long> asList) {
        for (Long id : asList) {
            BusTable busTable = this.getById(id);
            if (this.iBusTableColumnService.removeByTableName(busTable.getBusTableName())) {
                if (iDynamicSqlService.exitTable(busTable.getBusTableName(),busTable.getDbName())) {
                    iDynamicSqlService.dropTable(busTable.getBusTableName(),busTable.getDbName(), busTable.getTableType());
                }
            }
        }
        return this.removeByIds(asList);
    }


}
